package org.ftc.web;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.log4j.Logger;
import org.ftc.form.FileDataForm;
import org.ftc.form.FileForm;
import org.ftc.service.FtcLogService;
import org.ftc.service.FtcLogService.Log;
import org.ftc.util.Global;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

@Controller
public class FilesController {
	// log
//	protected Logger logger = Logger.getLogger(getClass());

	@Autowired
	private FtcLogService logService;

	@RequestMapping(value = "/files.htm")
	public String files(@RequestParam("id") String id, ModelMap model) {
		FileForm fileForm = new FileForm();
		fileForm.setSessionNo(id);
		model.addAttribute("fileForm", fileForm);//
		// 檢查資料夾是否已存在不存在則新增
		String sessionNo = StringUtils.leftPad(id, 5, "0");
		final String filePath1 = String.format("%s\\%s", Global.APP.IMAGE_PATH, StringUtils.substring(sessionNo, 0, 3));
		this.createDirectory(filePath1);
		final String filePath2 = String.format("%s\\%s\\%s", Global.APP.IMAGE_PATH,
				StringUtils.substring(sessionNo, 0, 3), sessionNo);
		this.createDirectory(filePath2);
		return "files/list";
	}

	@RequestMapping(value = "/files/save.json", method = RequestMethod.GET)
	public @ResponseBody FileForm dataList(@RequestParam("id") String id) {
		logService.before();
		String sessionNo = StringUtils.leftPad(id, 5, "0");
		final String filePath = String.format("%s\\%s\\%s", Global.APP.IMAGE_PATH,
				StringUtils.substring(sessionNo, 0, 3), sessionNo);
		PathMatcher PATH_MATCH = FileSystems.getDefault().getPathMatcher("glob:*.{pdf,tif}");
		List<FileDataForm> data = new ArrayList<>();
		if (Files.exists(Paths.get(filePath))) {
			try (Stream<Path> directoryStream = Files.list(Paths.get(filePath))) {
				directoryStream
						.parallel()
						.filter(path -> PATH_MATCH.matches(path.getFileName()))
						.sorted((path1, path2) -> path1.compareTo(path2))
						.forEachOrdered(
								path -> {
									FileDataForm form;
									try {
										form = new FileDataForm(path.getFileName().toString(), Files.size(path), path
												.getFileName().toString());
										data.add(form);
									} catch (Exception e) {
										e.printStackTrace();
									}
								});
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		FileForm result = new FileForm();
		result.setFiles(data);
		logService.save(Log.QUERY, id, this.getClass().toString(), ToStringBuilder.reflectionToString(data));
		return result;

	}

	@RequestMapping(value = "/files/save.json", method = RequestMethod.POST)
	public @ResponseBody FileForm save(@RequestParam(value = "sNo") String sNo, MultipartHttpServletRequest request,
			HttpServletResponse response) {
		logService.before();
		String sessionNo = StringUtils.leftPad(sNo, 5, "0");
		// 檔案路徑
		final String filePath = String.format("%s\\%s\\%s\\", Global.APP.IMAGE_PATH,
				StringUtils.substring(sessionNo, 0, 3), sessionNo);
		Iterator<String> itr = request.getFileNames();
		MultipartFile mpf = null;

		List<FileDataForm> data = new ArrayList<>();
		while (itr.hasNext()) {
			mpf = request.getFile(itr.next());
			FileDataForm form;
			try {
				Path path = Paths.get(filePath + mpf.getOriginalFilename());
				Files.write(path, mpf.getBytes());
				form = new FileDataForm(path.getFileName().toString(), Files.size(path), path.getFileName().toString());
				data.add(form);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		FileForm result = new FileForm();
		result.setFiles(data);
		logService.save(Log.INSERT, sNo, this.getClass().toString(), ToStringBuilder.reflectionToString(data));
		return result;

	}

	@RequestMapping(value = "/files/delete.json", method = RequestMethod.POST)
	public @ResponseBody boolean delete(@RequestParam("id") String id, @RequestParam("sessionNo") String sNo,
			ModelMap model) {
		boolean result = false;
		String sessionNo = StringUtils.leftPad(sNo, 5, "0");
		// 檔案路徑
		final String filePath = String.format("%s\\%s\\%s\\%s", Global.APP.IMAGE_PATH,
				StringUtils.substring(sessionNo, 0, 3), sessionNo, id);
		logService.before();
		try {
			result = Files.deleteIfExists(Paths.get(filePath));
			logService.save(Log.DELETE, id, this.getClass().toString());
		} catch (IOException e) {
			e.printStackTrace();
			result = false;
		}
		return result;

	}

	/**
	 * 匯出檔案
	 * 
	 * @param motionForm
	 * @param response
	 */
	@RequestMapping(value = "/files/exp.htm", method = RequestMethod.POST)
	public void export(FileForm fileForm, HttpServletResponse response) {
		logService.before();
		String sessionNo = StringUtils.leftPad(fileForm.getSessionNo(), 5, "0");
		try {
			final String filePath = String.format("%s\\%s\\%s\\%s", Global.APP.IMAGE_PATH,
					StringUtils.substring(sessionNo, 0, 3), sessionNo, fileForm.getFilename());
			response.setHeader("content-disposition", "attachment; filename=" + fileForm.getFilename());
			Files.copy(Paths.get(filePath), response.getOutputStream());
			logService.save(Log.DOWNLOAD, fileForm.getFilename(), this.getClass().toString());
			response.flushBuffer();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(Global.APP.DATE_FORMAT);
		dateFormat.setLenient(false);
		binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
	}

	private void createDirectory(String path) {
		if (!Files.isDirectory(Paths.get(path))) {
			try {
				Files.createDirectory(Paths.get(path));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
